home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / pythonscript.py < prev    next >
Text File  |  2008-10-15  |  31KB  |  819 lines

  1. # XScript implementation for python
  2. import uno
  3. import unohelper
  4. import sys
  5. import os
  6. import imp
  7. import time
  8.  
  9. class LogLevel:
  10.     NONE = 0
  11.     ERROR = 1
  12.     DEBUG = 2
  13.  
  14. # Configuration ----------------------------------------------------
  15. LogLevel.use = LogLevel.NONE                # production level
  16. #LogLevel.use = LogLevel.ERROR               # for script developers
  17. #LogLevel.use = LogLevel.DEBUG               # for script framework developers
  18. LOG_STDOUT = True                           # True, writes to stdout (difficult on windows)
  19.                                             # False, writes to user/Scripts/python/log.txt
  20. ENABLE_EDIT_DIALOG=False                    # offers a minimal editor for editing.
  21. #-------------------------------------------------------------------
  22.  
  23. def encfile(uni):
  24.     return uni.encode( sys.getfilesystemencoding())
  25.  
  26. def lastException2String():
  27.     (excType,excInstance,excTraceback) = sys.exc_info()
  28.     ret = str(excType) + ": "+str(excInstance) + "\n" + \
  29.           uno._uno_extract_printable_stacktrace( excTraceback )
  30.     return ret
  31.  
  32. def logLevel2String( level ):
  33.     ret = " NONE"
  34.     if level == LogLevel.ERROR:
  35.         ret = "ERROR"
  36.     elif level >= LogLevel.DEBUG:
  37.         ret = "DEBUG"
  38.     return ret
  39.  
  40. def getLogTarget():
  41.     ret = sys.stdout
  42.     if not LOG_STDOUT:
  43.         try:
  44.             pathSubst = uno.getComponentContext().ServiceManager.createInstance(
  45.                 "com.sun.star.util.PathSubstitution" )
  46.             userInstallation =  pathSubst.getSubstituteVariableValue( "user" )
  47.             if len( userInstallation ) > 0:
  48.                 systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" )
  49.                 ret = file( systemPath , "a" )
  50.         except Exception,e:
  51.             print "Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n"
  52.     return ret
  53.   
  54. class Logger(LogLevel):
  55.     def __init__(self , target ):
  56.         self.target = target
  57.  
  58.     def isDebugLevel( self ):
  59.         return self.use >= self.DEBUG
  60.     
  61.     def debug( self, msg ):
  62.         if self.isDebugLevel():
  63.             self.log( self.DEBUG, msg )
  64.     
  65.     def isErrorLevel( self ):
  66.         return self.use >= self.ERROR
  67.  
  68.     def error( self, msg ):
  69.         if self.isErrorLevel():
  70.             self.log( self.ERROR, msg )
  71.  
  72.     def log( self, level, msg ):
  73.         if self.use >= level:
  74.             try:
  75.                 self.target.write(
  76.                     time.asctime() +
  77.                     " [" +
  78.                     logLevel2String( level ) +
  79.                     "] " +
  80.                     encfile(msg) +
  81.                     "\n" )
  82.                 self.target.flush()
  83.             except Exception,e:
  84.                 print "Error during writing to stdout: " +lastException2String() + "\n"
  85.  
  86. log = Logger( getLogTarget() )
  87.  
  88. log.debug( "pythonscript loading" )
  89.  
  90. #from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider
  91. from com.sun.star.uno import RuntimeException
  92. from com.sun.star.lang import XServiceInfo
  93. from com.sun.star.io import IOException
  94. from com.sun.star.ucb import CommandAbortedException
  95. from com.sun.star.beans import XPropertySet
  96. from com.sun.star.container import XNameContainer
  97. from com.sun.star.xml.sax import XDocumentHandler, InputSource
  98. from com.sun.star.uno import Exception as UnoException
  99. from com.sun.star.script import XInvocation
  100. from com.sun.star.awt import XActionListener
  101.  
  102. from com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException
  103. from com.sun.star.script.browse import XBrowseNode
  104. from com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT
  105.  
  106. LANGUAGENAME = "Python"
  107. GLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT"
  108. CALLABLE_CONTAINER_NAME =  "g_exportedScripts"
  109.  
  110. # pythonloader looks for a static g_ImplementationHelper variable
  111. g_ImplementationHelper = unohelper.ImplementationHelper()
  112. g_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME
  113.  
  114.  
  115.  
  116. BLOCK_SIZE = 65536
  117. def readTextFromStream( inputStream ):
  118.     # read the file
  119.     code = uno.ByteSequence( "" )
  120.     while True:
  121.         read,out = inputStream.readBytes( None , BLOCK_SIZE )
  122.         code = code + out
  123.         if read < BLOCK_SIZE:
  124.            break
  125.     return code.value
  126.     
  127.     
  128. class ModuleEntry:
  129.     def __init__( self, lastRead, module ):
  130.         self.lastRead = lastRead
  131.         self.module = module
  132.  
  133. def hasChanged( oldDate, newDate ):
  134.     return newDate.Year > oldDate.Year or \
  135.            newDate.Month > oldDate.Month or \
  136.            newDate.Day > oldDate.Day or \
  137.            newDate.Hours > oldDate.Hours or \
  138.            newDate.Minutes > oldDate.Minutes or \
  139.            newDate.Seconds > oldDate.Seconds or \
  140.            newDate.HundredthSeconds > oldDate.HundredthSeconds
  141.  
  142. def ensureSourceState( code ):
  143.     if not code.endswith( "\n" ):
  144.         code = code + "\n"
  145.     code = code.replace( "\r", "" )
  146.     return code
  147.  
  148.  
  149. def checkForPythonPathBesideScript( url ):
  150.     if url.startswith( "file:" ):
  151.         path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
  152.         log.log( LogLevel.DEBUG,  "checking for existence of " + path )
  153.         if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
  154.             log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
  155.             sys.path.append( path )
  156.  
  157.         path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
  158.         log.log( LogLevel.DEBUG,  "checking for existence of " + path )
  159.         if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
  160.             log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
  161.             sys.path.append( path )
  162.         
  163.     
  164. class ScriptContext(unohelper.Base):
  165.     def __init__( self, ctx, doc ):
  166.         self.ctx = ctx
  167.         self.doc = doc
  168.        
  169.    # XScriptContext
  170.     def getDocument(self):
  171.         return self.getDesktop().getCurrentComponent()
  172.  
  173.     def getDesktop(self):
  174.         return self.ctx.ServiceManager.createInstanceWithContext(
  175.             "com.sun.star.frame.Desktop", self.ctx )
  176.  
  177.     def getComponentContext(self):
  178.         return self.ctx
  179.  
  180. #----------------------------------
  181. # Global Module Administration
  182. # does not fit together with script
  183. # engine lifetime management
  184. #----------------------------------
  185. #g_scriptContext = ScriptContext( uno.getComponentContext(), None )
  186. #g_modules = {}
  187. #def getModuleByUrl( url, sfa ):
  188. #    entry =  g_modules.get(url)
  189. #    load = True
  190. #    lastRead = sfa.getDateTimeModified( url )
  191. #    if entry:
  192. #        if hasChanged( entry.lastRead, lastRead ):
  193. #            log.isDebugLevel() and log.debug("file " + url + " has changed, reloading")
  194. #        else:
  195. #            load = False
  196. #            
  197. #    if load:
  198. #        log.isDebugLevel() and log.debug( "opening >" + url + "<" )
  199. #
  200. #        code = readTextFromStream( sfa.openFileRead( url ) )
  201.             
  202.         # execute the module
  203. #        entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") )
  204. #        entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext
  205. #        entry.module.__file__ = url
  206. #        exec code in entry.module.__dict__
  207. #        g_modules[ url ] = entry
  208. #        log.isDebugLevel() and log.debug( "mapped " + url + " to " + str( entry.module ) )
  209. #    return entry.module
  210.  
  211. class ProviderContext:
  212.     def __init__( self, storageType, sfa, uriHelper, scriptContext ):
  213.         self.storageType = storageType
  214.         self.sfa = sfa
  215.         self.uriHelper = uriHelper
  216.         self.scriptContext = scriptContext
  217.         self.modules = {}
  218.         self.rootUrl = None
  219.         self.mapPackageName2Path = None
  220.  
  221.     def getTransientPartFromUrl( self, url ):
  222.         rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
  223.         return rest[0:rest.find("/")]
  224.     
  225.     def getPackageNameFromUrl( self, url ):
  226.         rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
  227.         start = rest.find("/") +1
  228.         return rest[start:rest.find("/",start)]
  229.         
  230.         
  231.     def removePackageByUrl( self, url ):
  232.         items = self.mapPackageName2Path.items()
  233.         for i in items:
  234.             if url in i[1].pathes:
  235.                 self.mapPackageName2Path.pop(i[0])
  236.                 break
  237.  
  238.     def addPackageByUrl( self, url ):
  239.         packageName = self.getPackageNameFromUrl( url )
  240.         transientPart = self.getTransientPartFromUrl( url )
  241.         log.isDebugLevel() and log.debug( "addPackageByUrl : " + packageName + ", " + transientPart )
  242.         if self.mapPackageName2Path.has_key( packageName ):
  243.             package = self.mapPackageName2Path[ packageName ]
  244.             package.pathes = package.pathes + (url, )
  245.         else:
  246.             package = Package( (url,), transientPart)
  247.             self.mapPackageName2Path[ packageName ] = package
  248.     
  249.     def isUrlInPackage( self, url ):
  250.         values = self.mapPackageName2Path.values()
  251.         for i in values:
  252.             if url in i.pathes:
  253.                return True
  254.         return False
  255.             
  256.     def setPackageAttributes( self, mapPackageName2Path, rootUrl ):
  257.         self.mapPackageName2Path = mapPackageName2Path
  258.         self.rootUrl = rootUrl
  259.         
  260.     def getPersistentUrlFromStorageUrl( self, url ):
  261.         # package name is the second directory
  262.         ret = url
  263.         if self.rootUrl:
  264.             pos = len( self.rootUrl) +1
  265.             ret = url[0:pos]+url[url.find("/",pos)+1:len(url)]
  266.         log.isDebugLevel() and log.debug( "getPersistentUrlFromStorageUrl " + url +  " -> "+ ret)
  267.         return ret
  268.  
  269.     def getStorageUrlFromPersistentUrl( self, url):
  270.         ret = url
  271.         if self.rootUrl:
  272.             pos = len(self.rootUrl)+1
  273.             packageName = url[pos:url.find("/",pos+1)]
  274.             package = self.mapPackageName2Path[ packageName ]
  275.             ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)]
  276.         log.isDebugLevel() and log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret)
  277.         return ret
  278.     
  279.     def getModuleByUrl( self, url ):
  280.         entry =  self.modules.get(url)
  281.         load = True
  282.         lastRead = self.sfa.getDateTimeModified( url )
  283.         if entry:
  284.             if hasChanged( entry.lastRead, lastRead ):
  285.                 log.isDebugLevel() and log.debug( "file " + url + " has changed, reloading" )
  286.             else:
  287.                 load = False
  288.                 
  289.         if load:
  290.             log.isDebugLevel() and log.debug( "opening >" + url + "<" )
  291.             
  292.             src = readTextFromStream( self.sfa.openFileRead( url ) )
  293.             checkForPythonPathBesideScript( url[0:url.rfind('/')] )
  294.             src = ensureSourceState( src )            
  295.             
  296.             # execute the module
  297.             entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") )
  298.             entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext
  299.  
  300.             code = None
  301.             if url.startswith( "file:" ):
  302.                 code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" )
  303.             else:
  304.                 code = compile( src, url, "exec" )
  305.             exec code in entry.module.__dict__
  306.             entry.module.__file__ = url
  307.             self.modules[ url ] = entry
  308.             log.isDebugLevel() and log.debug( "mapped " + url + " to " + str( entry.module ) )
  309.         return  entry.module
  310.         
  311. #--------------------------------------------------
  312. def isScript( candidate ):
  313.     ret = False
  314.     if isinstance( candidate, type(isScript) ):
  315.         ret = True
  316.     return ret
  317.     
  318. #-------------------------------------------------------
  319. class ScriptBrowseNode( unohelper.Base, XBrowseNode , XPropertySet, XInvocation, XActionListener ):
  320.     def __init__( self, provCtx, uri, fileName, funcName, func ):
  321.         self.fileName = fileName
  322.         self.funcName = funcName
  323.         self.provCtx = provCtx
  324.         self.func = func
  325.         self.uri = uri
  326.         
  327.     def getName( self ):
  328.         return self.funcName
  329.  
  330.     def getChildNodes(self):
  331.         return ()
  332.  
  333.     def hasChildNodes(self):
  334.         return False
  335.     
  336.     def getType( self):
  337.         return SCRIPT
  338.  
  339.     def getPropertyValue( self, name ):
  340.         ret = None
  341.         if name == "URI":
  342.             ret = self.provCtx.uriHelper.getScriptURI(
  343.                 self.provCtx.getPersistentUrlFromStorageUrl( self.uri + "$" + self.funcName ) )
  344.         elif name == "Description":
  345.             ret = getattr( self.func, "__doc__", None )
  346.         elif name == "Editable" and ENABLE_EDIT_DIALOG:
  347.             ret = not self.provCtx.sfa.isReadOnly( self.uri )
  348.         
  349.         log.isDebugLevel() and log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) )
  350.         return ret
  351.     def setPropertyValue( self, name, value ):
  352.         log.isDebugLevel() and log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) )
  353.     def getPropertySetInfo( self ):
  354.         log.isDebugLevel() and log.debug( "ScriptBrowseNode.getPropertySetInfo called "  )
  355.         return None
  356.                
  357.     def getIntrospection( self ):
  358.         return None
  359.  
  360.     def invoke( self, name, params, outparamindex, outparams ):
  361.         if name == "Editable":
  362.             servicename = "com.sun.star.awt.DialogProvider"
  363.             ctx = self.provCtx.scriptContext.getComponentContext()
  364.             dlgprov = ctx.ServiceManager.createInstanceWithContext(
  365.                 servicename, ctx )
  366.  
  367.             self.editor = dlgprov.createDialog(
  368.                 "vnd.sun.star.script:" +
  369.                 "ScriptBindingLibrary.MacroEditor?location=application")
  370.  
  371.             code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri))
  372.             code = ensureSourceState( code )
  373.             self.editor.getControl("EditorTextField").setText(code)
  374.  
  375.             self.editor.getControl("RunButton").setActionCommand("Run")
  376.             self.editor.getControl("RunButton").addActionListener(self)
  377.             self.editor.getControl("SaveButton").setActionCommand("Save")
  378.             self.editor.getControl("SaveButton").addActionListener(self)
  379.  
  380.             self.editor.execute()
  381.  
  382.         return None
  383.  
  384.     def actionPerformed( self, event ):
  385.         try:
  386.             if event.ActionCommand == "Run":
  387.                 code = self.editor.getControl("EditorTextField").getText()
  388.                 code = ensureSourceState( code )
  389.                 mod = imp.new_module("ooo_script_framework")
  390.                 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext
  391.                 exec code in mod.__dict__
  392.                 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None )
  393.                 if not values:
  394.                     values = mod.__dict__.values()
  395.                     
  396.                 for i in values:
  397.                     if isScript( i ):
  398.                         i()
  399.                         break
  400.                     
  401.             elif event.ActionCommand == "Save":
  402.                 toWrite = uno.ByteSequence(
  403.                     str(
  404.                     self.editor.getControl("EditorTextField").getText().encode(
  405.                     sys.getdefaultencoding())) )
  406.                 copyUrl = self.uri + ".orig"
  407.                 self.provCtx.sfa.move( self.uri, copyUrl )
  408.                 out = self.provCtx.sfa.openFileWrite( self.uri )
  409.                 out.writeBytes( toWrite )
  410.                 out.close()
  411.                 self.provCtx.sfa.kill( copyUrl )
  412. #                log.isDebugLevel() and log.debug("Save is not implemented yet")
  413. #                text = self.editor.getControl("EditorTextField").getText()
  414. #                log.isDebugLevel() and log.debug("Would save: " + text)
  415.         except Exception,e:
  416.             # TODO: add an error box here !
  417.             log.error( lastException2String() )
  418.             
  419.  
  420.     def setValue( self, name, value ):
  421.         return None
  422.  
  423.     def getValue( self, name ):
  424.         return None
  425.  
  426.     def hasMethod( self, name ):
  427.         return False
  428.  
  429.     def hasProperty( self, name ):
  430.         return False
  431.  
  432.     
  433. #-------------------------------------------------------
  434. class FileBrowseNode( unohelper.Base, XBrowseNode ):
  435.     def __init__( self, provCtx, uri , name ):
  436.         self.provCtx = provCtx
  437.         self.uri = uri
  438.         self.name = name
  439.         self.module = None
  440.         
  441.     def getName( self ):
  442.         return self.name
  443.  
  444.     def getChildNodes(self):
  445.         ret = ()
  446.         try:
  447.             self.module = self.provCtx.getModuleByUrl( self.uri )
  448.             values = self.module.__dict__.get( CALLABLE_CONTAINER_NAME , None )
  449.             
  450.             # no g_exportedScripts, export every function
  451.             if not isinstance(values, type(())):
  452.                 values = self.module.__dict__.values()
  453.                     
  454.             scriptNodeList = []
  455.             for i in values:
  456.                 if isScript( i ):
  457.                     scriptNodeList.append(
  458.                         ScriptBrowseNode(
  459.                         self.provCtx, self.uri, self.name, i.__name__, i  ))
  460.             ret = tuple( scriptNodeList )
  461.             # must compile  !
  462.             log.isDebugLevel() and log.debug( "returning " +str(len(ret)) + " ScriptChildNodes on " + self.uri )
  463.         except Exception, e:
  464.             text = lastException2String()
  465.             log.error( "Error while evaluating " + self.uri + ":" + text )
  466.             raise
  467.         return ret
  468.  
  469.     def hasChildNodes(self):
  470.         try:
  471.             return len(self.getChildNodes()) > 0
  472.         except Exception, e:
  473.             return False
  474.     
  475.     def getType( self):
  476.         return CONTAINER
  477.  
  478.         
  479.  
  480. class DirBrowseNode( unohelper.Base, XBrowseNode ):
  481.     def __init__( self, provCtx, name, rootUrl ):
  482.         self.provCtx = provCtx
  483.         self.name = name
  484.         self.rootUrl = rootUrl
  485.  
  486.     def getName( self ):
  487.         return self.name
  488.  
  489.     def getChildNodes( self ):
  490.         try:
  491.             log.isDebugLevel() and log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl )
  492.             contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True )
  493.             browseNodeList = []
  494.             for i in contents:
  495.                 if i.endswith( ".py" ):
  496.                     log.isDebugLevel() and log.debug( "adding filenode " + i )
  497.                     browseNodeList.append(
  498.                         FileBrowseNode( self.provCtx, i, i[i.rfind("/")+1:len(i)-3] ) )
  499.                 elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"):
  500.                     log.isDebugLevel() and log.debug( "adding DirBrowseNode " + i )
  501.                     browseNodeList.append( DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)],i))
  502.             return tuple( browseNodeList )
  503.         except Exception, e:
  504.             text = lastException2String()
  505.             log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl)
  506.             log.error( text)
  507.             return ()
  508.  
  509.     def hasChildNodes( self ):
  510.         return True
  511.  
  512.     def getType( self ):
  513.         return CONTAINER
  514.  
  515.     def getScript( self, uri ):
  516.         log.debug( "DirBrowseNode getScript " + uri + " invoked" )
  517.         raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )
  518.  
  519.  
  520. class ManifestHandler( XDocumentHandler, unohelper.Base ):
  521.     def __init__( self, rootUrl ):
  522.         self.rootUrl = rootUrl
  523.         
  524.     def startDocument( self ):
  525.         self.urlList = []
  526.         
  527.     def endDocument( self ):
  528.         pass
  529.         
  530.     def startElement( self , name, attlist):
  531.         if name == "manifest:file-entry":
  532.             if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script":
  533.                 self.urlList.append(
  534.                     self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) )
  535.  
  536.     def endElement( self, name ):
  537.         pass
  538.  
  539.     def characters ( self, chars ):
  540.         pass
  541.  
  542.     def ignoreableWhitespace( self, chars ):
  543.         pass
  544.  
  545.     def setDocumentLocator( self, locator ):
  546.         pass
  547.  
  548.  
  549. # extracts META-INF directory from 
  550. def getPathesFromPackage( rootUrl, sfa ):
  551.     ret = ()
  552.     try:
  553.         fileUrl = rootUrl + "/META-INF/manifest.xml" 
  554.         inputStream = sfa.openFileRead( fileUrl )
  555.         parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" )
  556.         handler = ManifestHandler( rootUrl )
  557.         parser.setDocumentHandler( handler )
  558.         parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) )
  559.         ret = tuple( handler.urlList )
  560.     except UnoException, e:
  561.         text = lastException2String()
  562.         log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text )
  563.         pass
  564.     return ret
  565.     
  566.  
  567. class Package:
  568.     def __init__( self, pathes, transientPathElement ):
  569.         self.pathes = pathes
  570.         self.transientPathElement = transientPathElement
  571.  
  572. def getPackageName2PathMap( sfa, rootUrl ):
  573.     ret = {}
  574.     contents = sfa.getFolderContents( rootUrl, True )
  575.     for i in contents:
  576.         if sfa.isFolder( i ):
  577.             transientPathElement = lastElement( i )
  578.             subcontents = sfa.getFolderContents( i , True )
  579.             for j in subcontents:
  580.                 if sfa.isFolder( j ):
  581.                     # ok, found a package. Now let's have a look, if
  582.                     # it contains scripts
  583.                     pathes = getPathesFromPackage( j, sfa )
  584.                     if len( pathes ) > 0:
  585.                         # map package name to url, we need this later
  586.                         log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) )
  587.                         ret[ lastElement( j ) ] = Package( pathes, transientPathElement )
  588.     return ret
  589.  
  590. def lastElement( aStr):
  591.     return aStr[ aStr.rfind( "/" )+1:len(aStr)]
  592.  
  593. class PackageBrowseNode( unohelper.Base, XBrowseNode ):
  594.     def __init__( self, provCtx, name, rootUrl ):
  595.         self.provCtx = provCtx
  596.         self.name = name
  597.         self.rootUrl = rootUrl
  598.  
  599.     def getName( self ):
  600.         return self.name
  601.  
  602.     def getChildNodes( self ):
  603.         items = self.provCtx.mapPackageName2Path.items()
  604.         browseNodeList = []
  605.         for i in items:
  606.             if len( i[1].pathes ) == 1:
  607.                 browseNodeList.append(
  608.                     DirBrowseNode( self.provCtx, i[0], i[1].pathes[0] ))
  609.             else:
  610.                 for j in i[1].pathes:
  611.                     browseNodeList.append(
  612.                         DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j ) )
  613.         return tuple( browseNodeList )
  614.  
  615.     def hasChildNodes( self ):
  616.         return len( self.mapPackageName2Path ) > 0
  617.  
  618.     def getType( self ):
  619.         return CONTAINER
  620.  
  621.     def getScript( self, uri ):
  622.         log.debug( "DirBrowseNode getScript " + uri + " invoked" )
  623.         raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 )
  624.  
  625.  
  626.  
  627.  
  628. class PythonScript( unohelper.Base, XScript ):
  629.     def __init__( self, func, mod ):
  630.         self.func = func
  631.         self.mod = mod
  632.     def invoke(self, args, out, outindex ):
  633.         log.isDebugLevel() and log.debug( "PythonScript.invoke " + str( args ) )
  634.         try:
  635.             ret = self.func( *args )
  636.         except UnoException,e:
  637.             # UNO Exception continue to fly ...
  638.             text = lastException2String()
  639.             complete = "Error during invoking function " + \
  640.                 str(self.func.__name__) + " in module " + \
  641.                 self.mod.__file__ + " (" + text + ")"
  642.             log.isDebugLevel() and log.debug( complete )
  643.             # some people may beat me up for modifying the exception text,
  644.             # but otherwise office just shows
  645.             # the type name and message text with no more information,
  646.             # this is really bad for most users. 
  647.             e.Message = e.Message + " (" + complete + ")"
  648.             raise
  649.         except Exception,e:
  650.             # General python exception are converted to uno RuntimeException
  651.             text = lastException2String()
  652.             complete = "Error during invoking function " + \
  653.                 str(self.func.__name__) + " in module " + \
  654.                 self.mod.__file__ + " (" + text + ")"
  655.             log.isDebugLevel() and log.debug( complete )
  656.             raise RuntimeException( complete , self )
  657.         log.isDebugLevel() and log.debug( "PythonScript.invoke ret = " + str( ret ) )
  658.         return ret, (), ()
  659.  
  660. def expandUri(  uri ):
  661.     if uri.startswith( "vnd.sun.star.expand:" ):
  662.         uri = uri.replace( "vnd.sun.star.expand:", "",1)
  663.         uri = uno.getComponentContext().getByName(
  664.                     "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri )
  665.     return uri
  666.     
  667. #--------------------------------------------------------------
  668. class PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer):
  669.     def __init__( self, ctx, *args ):
  670.         if log.isDebugLevel():
  671.             mystr = ""
  672.             for i in args:
  673.                 if len(mystr) > 0:
  674.                     mystr = mystr +","
  675.                 mystr = mystr + str(i)
  676.             log.debug( "Entering PythonScriptProvider.ctor" + mystr )
  677.  
  678.         storageType = ""
  679.         if isinstance(args[0],unicode ):
  680.             storageType = args[0]
  681.         else:
  682.             storageType = args[0].SCRIPTING_DOC_URI
  683.         isPackage = storageType.endswith( ":uno_packages" )
  684.  
  685.         try:
  686.             urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext(
  687.                 "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx)
  688.             
  689.             log.isDebugLevel() and log.debug( "got urlHelper " + str( urlHelper ) )
  690.         
  691.             rootUrl = urlHelper.getRootStorageURI()
  692.             log.isDebugLevel() and log.debug( storageType + " transformed to " + rootUrl )
  693.  
  694.             ucbService = "com.sun.star.ucb.SimpleFileAccess"
  695.             sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx )
  696.             if not sfa:
  697.                 log.debug("PythonScriptProvider couldn't instantiate " +ucbService)
  698.                 raise RuntimeException(
  699.                     "PythonScriptProvider couldn't instantiate " +ucbService, self)
  700.             self.provCtx = ProviderContext(
  701.                 storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), None ) )
  702.             if isPackage:
  703.                 mapPackageName2Path = getPackageName2PathMap( sfa, rootUrl )
  704.                 self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl )
  705.                 self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
  706.             else:
  707.                 self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
  708.             
  709.         except Exception, e:
  710.             text = lastException2String()
  711.             log.debug( "PythonScriptProvider could not be instantiated because of : " + text )
  712.             raise e
  713.  
  714.     def getName( self ):
  715.         return self.dirBrowseNode.getName()
  716.  
  717.     def getChildNodes( self ):
  718.         return self.dirBrowseNode.getChildNodes()    
  719.  
  720.     def hasChildNodes( self ):
  721.         return self.dirBrowseNode.hasChildNodes()
  722.  
  723.     def getType( self ):
  724.         return self.dirBrowseNode.getType()
  725.  
  726.     def getScript( self, uri ):
  727.         log.debug( "DirBrowseNode getScript " + uri + " invoked" )
  728.         
  729.         raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )
  730.  
  731.     def getScript( self, scriptUri ):
  732.         try:
  733.             log.isDebugLevel() and log.debug( "getScript " + scriptUri + " invoked")
  734.             
  735.             storageUri = self.provCtx.getStorageUrlFromPersistentUrl(
  736.                 self.provCtx.uriHelper.getStorageURI(scriptUri) );
  737.             log.isDebugLevel() and log.debug( "getScript: storageUri = " + storageUri)
  738.             fileUri = storageUri[0:storageUri.find( "$" )]
  739.             funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)]        
  740.             
  741.             mod = self.provCtx.getModuleByUrl( fileUri )
  742.             log.isDebugLevel() and log.debug( " got mod " + str(mod) )
  743.             
  744.             func = mod.__dict__[ funcName ]
  745.  
  746.             log.isDebugLevel() and log.debug( "got func " + str( func ) )
  747.             return PythonScript( func, mod )
  748.         except Exception, e:
  749.             text = lastException2String()
  750.             log.error( text )
  751.             raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 )
  752.         
  753.  
  754.     # XServiceInfo
  755.     def getSupportedServices( self ):
  756.         return g_ImplementationHelper.getSupportedServices(g_implName)
  757.  
  758.     def supportsService( self, ServiceName ):
  759.         return g_ImplementationHelper.supportsService( g_implName, ServiceName )
  760.  
  761.     def getImplementationName(self):
  762.         return g_implName
  763.  
  764.     def getByName( self, name ):
  765.         log.debug( "getByName called" + str( name ))
  766.         return None
  767.  
  768.         
  769.     def getElementNames( self ):
  770.         log.debug( "getElementNames called")
  771.         return ()
  772.     
  773.     def hasByName( self, name ):
  774.         try:
  775.             log.debug( "hasByName called " + str( name ))
  776.             uri = expandUri(name)
  777.             ret = self.provCtx.isUrlInPackage( uri )
  778.             log.debug( "hasByName " + uri + " " +str( ret ) )
  779.             return ret
  780.         except Exception, e:
  781.             text = lastException2String()
  782.             log.debug( "Error in hasByName:" +  text )
  783.             return False
  784.  
  785.     def removeByName( self, name ):
  786.         log.debug( "removeByName called" + str( name ))
  787.         uri = expandUri( name )
  788.         self.provCtx.removePackageByUrl( uri )
  789.         log.debug( "removeByName called" + str( uri ) + " successful" )
  790.         
  791.     def insertByName( self, name, value ):
  792.         log.debug( "insertByName called " + str( name ) + " " + str( value ))
  793.         uri = expandUri( name )
  794.         self.provCtx.addPackageByUrl( uri )
  795.         log.debug( "insertByName called" + str( uri ) + " successful" )
  796.  
  797.     def replaceByName( self, name, value ):
  798.         log.debug( "replaceByName called " + str( name ) + " " + str( value ))
  799.         removeByName( name )
  800.         insertByName( name )
  801.         log.debug( "replaceByName called" + str( uri ) + " successful" )
  802.  
  803.     def getElementType( self ):
  804.         log.debug( "getElementType called" )
  805.         return uno.getTypeByName( "void" )
  806.     
  807.     def hasElements( self ):
  808.         log.debug( "hasElements got called")
  809.         return False
  810.     
  811. g_ImplementationHelper.addImplementation( \
  812.     PythonScriptProvider,g_implName, \
  813.     ("com.sun.star.script.provider.LanguageScriptProvider",
  814.      "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),)
  815.  
  816.  
  817. log.debug( "pythonscript finished intializing" )
  818.  
  819.